package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"data-treating/pkg/analysis"
	"data-treating/pkg/types"
)

// ConvertedPoseData represents the structure of our converted data
type ConvertedPoseData struct {
	PoseData struct {
		Keypoints []struct {
			X          float64 `json:"x"`
			Y          float64 `json:"y"`
			Confidence float64 `json:"confidence"`
		} `json:"keypoints"`
		Timestamp int64 `json:"timestamp"`
		FrameID   int   `json:"frame_id"`
	} `json:"pose_data"`
}

func main() {
	// Read the converted data file
	data, err := os.ReadFile("../converted_sample_pose_data.json")
	if err != nil {
		log.Fatalf("Failed to read file: %v", err)
	}

	var convertedData []ConvertedPoseData
	if err := json.Unmarshal(data, &convertedData); err != nil {
		log.Fatalf("Failed to parse JSON: %v", err)
	}

	fmt.Printf("Loaded %d pose data entries\n", len(convertedData))

	// Use first 20 frames for calibration
	calibrationFrames := 20
	if len(convertedData) < calibrationFrames {
		log.Fatalf("Not enough data for calibration. Need at least %d frames, got %d", calibrationFrames, len(convertedData))
	}

	// Create analyzer and get its calibrator
	analyzer := analysis.NewPoseAnalyzer()
	calibrator := analyzer.GetCalibrator()

	// Convert and add calibration data
	fmt.Printf("Using first %d frames for calibration\n", calibrationFrames)
	for i := 0; i < calibrationFrames; i++ {
		pose := convertToPoseData(convertedData[i])
		calibrator.AddCalibrationFrame(pose)
	}

	// Perform calibration
	if err := calibrator.PerformCalibration(); err != nil {
		log.Fatalf("Calibration failed: %v", err)
	}

	fmt.Printf("Calibration completed successfully\n")
	fmt.Printf("Average pose computed with %d frames\n", calibrationFrames)
	fmt.Printf("Standard deviations calculated\n")

	// Test with remaining frames for assessment
	assessmentFrames := len(convertedData) - calibrationFrames
	fmt.Printf("\nTesting with remaining %d frames for assessment\n", assessmentFrames)

	// Process each assessment frame
	for i := calibrationFrames; i < len(convertedData); i++ {
		currentPose := convertToPoseData(convertedData[i])
		frameID := i + 1

		fmt.Printf("\n--- Frame %d (Timestamp: %d) ---\n", frameID, convertedData[i].PoseData.Timestamp)

		// Analyze pose
		result, err := analyzer.AnalyzePose(currentPose)
		if err != nil {
			fmt.Printf("Analysis failed: %v\n", err)
			continue
		}

		// Print analysis results
		fmt.Printf("Body Lean Forward: %.2f°\n", result.BodyLeanForward)
		fmt.Printf("Body Lean Backward: %.2f°\n", result.BodyLeanBackward)
		fmt.Printf("Head Turn Left: %.2f°\n", result.HeadTurnLeft)
		fmt.Printf("Head Turn Right: %.2f°\n", result.HeadTurnRight)
		fmt.Printf("Head Tilt Forward: %.2f°\n", result.HeadTiltForward)
		fmt.Printf("Head Tilt Backward: %.2f°\n", result.HeadTiltBackward)
		fmt.Printf("Legs Straight: %t\n", result.LegsStraight)
		fmt.Printf("Overall Score: %.1f/100\n", result.OverallScore)
		fmt.Printf("Confidence: %.2f\n", result.Confidence)

		// Add some delay to make output readable
		time.Sleep(100 * time.Millisecond)
	}

	fmt.Printf("\n=== Testing Summary ===\n")
	fmt.Printf("Calibration frames: %d\n", calibrationFrames)
	fmt.Printf("Assessment frames: %d\n", assessmentFrames)
	fmt.Printf("Total frames processed: %d\n", len(convertedData))
}

func convertToPoseData(converted ConvertedPoseData) types.PoseData {
	pose := types.PoseData{
		Timestamp: converted.PoseData.Timestamp,
		FrameID:   converted.PoseData.FrameID,
	}

	// Ensure we have exactly 17 keypoints
	for i := 0; i < 17 && i < len(converted.PoseData.Keypoints); i++ {
		pose.Keypoints[i] = types.Point{
			X:          converted.PoseData.Keypoints[i].X,
			Y:          converted.PoseData.Keypoints[i].Y,
			Confidence: converted.PoseData.Keypoints[i].Confidence,
		}
	}

	return pose
}
